#include <rthw.h>
#include <rtthread.h>
#include <stdint.h>
#include "SEGGER_RTT.h"
#include "ch32f20x.h"

extern uint32_t SystemCoreClock;

static uint32_t _SysTick_Config(rt_uint32_t ticks)
{
    if (ticks > SysTick_LOAD_RELOAD_Msk)
    {
        return (1); /* Reload value impossible */
    }

    NVIC_SetPriority(SysTick_IRQn, 0xFF);
    SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
    SysTick->VAL = 0;                                      /* Load the SysTick Counter Value */
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk |
                    SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
    return (0);                              /* Function successful */
}

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
/*
 * Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP
 * the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes
 */
#define RT_HEAP_SIZE (15 * 1024)
static rt_uint8_t rt_heap[RT_HEAP_SIZE];

RT_WEAK void *rt_heap_begin_get(void)
{
    return rt_heap;
}

RT_WEAK void *rt_heap_end_get(void)
{
    return rt_heap + RT_HEAP_SIZE;
}
#endif

void SysTick_Handler(void)
{
    rt_interrupt_enter();

    rt_tick_increase();

    rt_interrupt_leave();
}

/**
 * This function will initial your board.
 */
void rt_hw_board_init(void)
{
    SystemCoreClockUpdate();
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}

#ifdef RT_USING_CONSOLE

int log_system_core_clock(void)
{
    rt_kprintf("SystemCoreClock: %dHz\n", SystemCoreClock);
    return 0;
}
INIT_PREV_EXPORT(log_system_core_clock);

static int segger_rtt_console_init(void)
{
    SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
    return 0;
}
INIT_BOARD_EXPORT(segger_rtt_console_init);

void rt_hw_console_output(const char *str)
{
    SEGGER_RTT_Write(0, str, rt_strlen(str));
}

#endif
